package cn.witsky.rtp2ws.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.Thread.State;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import cn.witsky.rtp2ws.Server;
import cn.witsky.rtp2ws.cache.UdpServerManager;
import cn.witsky.rtp2ws.config.AppConfig;
import cn.witsky.rtp2ws.config.Config;
import cn.witsky.rtp2ws.domain.CallInfo;
import cn.witsky.rtp2ws.push.retry.RetryManager;
import cn.witsky.rtp2ws.util.FileUtil;
import cn.witsky.rtp2ws.util.NetWorkUtil;
import cn.witsky.rtp2ws.util.SignUtils;
import cn.witsky.rtp2ws.util.SystemClock;
import io.netty.util.internal.StringUtil;
import net.sf.json.JSONObject;

@RestController
public class AsrServerController {
	@Autowired
	Config config;

	@Autowired
	AppConfig appConfig;
	
	private static Logger logger = LoggerFactory.getLogger(AsrServerController.class);
	private static volatile Thread task = null;

	@RequestMapping(value = "workingTest")
	public void workingTest(HttpServletResponse resp) {
//		System.out.println(config.getHost("secret-axb-record-files.oss-cn-shanghai.aliyuncs.com"));
		// 将获取的json数据封装一层，然后在给返回
		JSONObject result = new JSONObject();
		result.put("code", 0);
		result.put("message", "success");
		// 写json数据到客户端
		this.writeJson(resp, result);
	}

	@RequestMapping(value = "/info")
	public void info(HttpServletResponse resp) {
		this.write(resp, Server.getServerInfo());
	}

	private void creatTeask() {
		task = new Thread(new Runnable() {
			@Override
			public void run() {
				List<String> lines = FileUtil.toArrayByFileReader();
				for (String callId : lines) {					
					boolean isSuc = RetryManager.offerCall(callId);
					if (!isSuc) {
						logger.warn("创建callId:{}的重传任务失败!", callId);
					} else {
						logger.info("创建callId:{}的重传任务成功!", callId);
					}
				}
			}
		});
		task.setName("rtp2ws-retry-trigger-Thread");
	}
	//curl  'http://192.168.150.39:30001/rtp2ws/offlineTransmissionBatch'
	@RequestMapping(value = "/offlineTransmissionBatch")
	public void offlineTransmissionBatch(HttpServletResponse resp) {
		// 将获取的json数据封装一层，然后在给返回
		JSONObject result = new JSONObject();
		synchronized (AsrServerController.class) {
			if(task!=null&&task.getState()==State.TERMINATED) {
				task=null;
			}
		}
		if (task == null) {
			synchronized (AsrServerController.class) {
				if(task==null) {
					this.creatTeask();
					task.start();
					result.put("code","0");
					result.put("message","重传任务开始执行");
				}else {
					result.put("code","-1");
					result.put("message","重传任务已经执行");
				}
			}
		}else {
				result.put("code","-1");
				result.put("message","重传任务已经执行");
		}
		// 写json数据到客户端
		this.writeJson(resp, result);
	}

	/**
	 * 通知打开udp端口
	 * 
	 * @return
	 */

	@RequestMapping(value = "/applyUdpResources", method = RequestMethod.POST)
	public void open(@RequestBody JSONObject jsonParam, HttpServletResponse resp) {
		logger.info("get port request:{}", jsonParam);
		// 将获取的json数据封装一层，然后在给返回
		JSONObject result = new JSONObject();
		CallInfo call = UdpServerManager.addCall(jsonParam);
		if (call == null || call.getUdpPort() == null) {
			result.put("code", "-1");
			result.put("message", "获取端口失败");
			result.put("data", new JSONObject());
		} else {
			String host = call.getRtp2wsHost();
			String ip = host.split(":")[0];
			JSONObject caller = new JSONObject();
			JSONObject called = new JSONObject();
			JSONObject data = new JSONObject();
			caller.put("port", call.getUdpPort());
			caller.put("ip", ip);
			called.put("port", call.getUdpPort() + 1);
			called.put("ip", ip);
			data.put("callId", call.getCallId());
			data.put("caller", caller);
			data.put("called", called);
			result.put("data", data);
			result.put("code", "0");
			result.put("message", "获取端口成功");
		}
		logger.info("get port result:{}", result);
		// 写json数据到客户端
		this.writeJson(resp, result);
	}

	/**
	 * 通知打开udp端口
	 * 
	 * @return
	 */

	@RequestMapping(value = "/releaseUdpResources", method = RequestMethod.POST)
	public void close(@RequestBody JSONObject jsonParam, HttpServletResponse resp) {
		// 将获取的json数据封装一层，然后在给返回
		logger.info("release port request:{}", jsonParam);
		JSONObject result = new JSONObject();
		String callId = jsonParam.getString("callId");
		String recordUrl=jsonParam.optString("recordDownloadUrl","");
//		String recordUrl = "https://secret-axb-record-files.oss-cn-shanghai.aliyuncs.com/0_436182305c070350_0.mp3?Expires=1638514216&OSSAccessKeyId=LTAI4G1kg5pSvJMv2rKNc7Pz&Signature=u/UiDMzmsAZdBYdGQN8FFK4ga6Q=";
//		String recordUrl ="http://10.137.172.158:20002/V2/20211012113811/ALI_A44616503232a7051_15934319899_18888888888_20211012113811.mp3";
		if(!StringUtil.isNullOrEmpty(recordUrl)) {
			String domain = NetWorkUtil.getDomain(recordUrl);
			String host = config.getHost(domain);
			if (!StringUtil.isNullOrEmpty(host)) {
				recordUrl = recordUrl.replace(domain, host);
			}
		}else {
			logger.warn("releaseUdpResources jsonParam:{} 缺少recordDownloadUrl值",jsonParam);
		}
		boolean isSuc = UdpServerManager.removeCall(callId, recordUrl);
		if (!isSuc) {
			result.put("code", "-1");
			result.put("message", "端口已经关闭了");
		} else {
			result.put("code", "0");
			result.put("message", "端口关闭成功");
		}
		// 写json数据到客户端
		this.writeJson(resp, result);
	}
	//curl -H "Content-Type:application/json" -X POST -d '{"callId":"192.168.150.39:8150_d9380fd3-c8a1-43ba-b687-36662a8ef0bb_0"}' 'http://192.168.150.39:30001/rtp2ws/offlineTransmission'
	@RequestMapping(value = "/offlineTransmission", method = RequestMethod.POST)
	public void offlineTransmission(@RequestBody JSONObject jsonParam, HttpServletResponse resp) {
		// 将获取的json数据封装一层，然后在给返回
		logger.info("offlineTransmission request:{}", jsonParam);
		JSONObject result = new JSONObject();
		String appKey = jsonParam.optString("appKey", "");
		String callId = jsonParam.optString("callId", "");
		String timeStamp = jsonParam.optString("timeStamp", "");
		String sign = jsonParam.optString("sign", "");
		boolean accept =true;
		if(Server.isSignature()) {
			accept = this.checkSign(appKey,callId, timeStamp, sign);
		}
		if (!accept) {
			result.put("code", "-1");
			result.put("message", "签名校验失败");
		} else {
			boolean isSuc = RetryManager.offerCall(callId);
			if (!isSuc) {
				result.put("code", "-1");
				result.put("message", "重传请求失败");
			} else {
				result.put("code", "0");
				result.put("message", "重传请求成功");
			}
		}

		// 写json数据到客户端
		this.writeJson(resp, result);
	}

	@RequestMapping(value = "/updateRtpSourceAddress", method = RequestMethod.POST)
	public void update(@RequestBody JSONObject jsonParam, HttpServletResponse resp) {
		// 将获取的json数据封装一层，然后在给返回
		JSONObject result = new JSONObject();
		boolean isSuc = UdpServerManager.mergeCall(jsonParam);
		if (!isSuc) {
			result.put("code", "-1");
			result.put("message", "会话不存在");
		} else {
			result.put("code", "0");
			result.put("message", "更新成功");
		}
		// 写json数据到客户端
		this.writeJson(resp, result);
	}

	@RequestMapping(value = "/rtp2ws/{method}", method = RequestMethod.POST)
	public void post(@RequestBody JSONObject jsonParam, HttpServletResponse resp, @PathVariable String method) {
		if (method.equals("applyUdpResources")) {
			this.open(jsonParam, resp);
		} else if (method.equals("releaseUdpResources")) {
			this.close(jsonParam, resp);
		} else if (method.equals("updateRtpSourceAddress")) {
			this.update(jsonParam, resp);
		} else if (method.equals("offlineTransmission")) {
			this.offlineTransmission(jsonParam, resp);
		} else {
			JSONObject result = new JSONObject();
			result.put("code", "-1");
			result.put("message", "非法的请求.....");
			this.writeJson(resp, result);
		}
	}

	@RequestMapping(value = "/rtp2ws/{method}", method = RequestMethod.GET)
	public void get(HttpServletResponse resp, @PathVariable String method) {
		if (method.equals("workingTest")) {
			this.workingTest(resp);
		} else if (method.equals("info")) {
			this.info(resp);
		} else if (method.equals("offlineTransmissionBatch")) {
			this.offlineTransmissionBatch(resp);
		} else {
			JSONObject result = new JSONObject();
			result.put("code", "-1");
			result.put("message", "非法的请求.....");
			this.writeJson(resp, result);
		}
	}

	private boolean checkSign(String appKey,String callId, String timeStamp, String sign) {
		if (StringUtil.isNullOrEmpty(appKey) ||StringUtil.isNullOrEmpty(callId) || StringUtil.isNullOrEmpty(timeStamp) || StringUtil.isNullOrEmpty(sign)) {
			logger.warn("请求的参数有空的");
			return false;
		}
		long now=SystemClock.now()/1000;
		logger.info("checkSign  now:{} timeStamp：{}",now,timeStamp);
		if(timeStamp.length()!=(now+"").length()) {
			logger.warn("时间戳参数不合法");
			return  false;
		}
		if(Long.parseLong(timeStamp)<now-300) {
			logger.warn("时间相差超过300秒");
			return  false;
		}
		String secret=appConfig.getSecretKey(appKey);
		if(StringUtil.isNullOrEmpty(secret)) {
			logger.warn("查找appKey:{}的secret是空",appKey);
			return false;
		}
		Map<String,String> params=new HashMap<String,String>();
		params.put("appKey", appKey);
		params.put("callId", callId);
		params.put("timeStamp", timeStamp);
		String encodeStr=SignUtils.signature(params, null, secret);
		logger.info("encodeStr:{}",encodeStr);
		return encodeStr.equals(sign);
	}
	
	

	/**
	 * 功能描述:写数据到浏览器上<br/>
	 * 
	 * @param resp
	 * @param json
	 */
	private void writeJson(HttpServletResponse resp, JSONObject json) {
		PrintWriter out = null;
		try {
			// 设定类容为json的格式
			resp.setContentType("application/json;charset=UTF-8");
			out = resp.getWriter();
			// 写到客户端
			out.write(json.toString());
			out.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				out.close();
			}
		}
	}

	/**
	 * 功能描述:写数据到浏览器上<br/>
	 * 
	 * @param resp
	 * @param json
	 */
	private void write(HttpServletResponse resp, String msg) {
		PrintWriter out = null;
		try {
			// 设定类容为json的格式
			resp.setContentType("text/plain;charset=UTF-8");
			out = resp.getWriter();
			// 写到客户端
			out.write(msg);
			out.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				out.close();
			}
		}
	}
}
